
from typing import List

from ninja import Router, Query
from ninja.pagination import paginate
from django.http import HttpResponse
from wechatpy import WeChatPay
from django.db import transaction

from apps.commom.order_response_schema import OrderInfoResponseSchema, VipOrderInfoResponseSchema, AgentOrderInfoResponseSchema
from apps.commom.order import OrderInfoSerializer, VipOrderInfoSerializer, AgentOrderInfoSerializer
from apps.manager.order_info_manager.schemas import ManagerOrderFiltersSchema, ManagerVipOrderFiltersSchema, \
    ManagerAgentOrderFiltersSchema, OrderUpdateLogisticsSchema, OrderRefundSchema
from apps.schemas import R
from models.choices import AfterSalesStatus
from models.models import OrderInfo, VipOrderInfo, AgentOrderInfo
from utils.auth import ManagerAuthBearer
from utils.decorators import handle_exception
from utils.file_handler import write_data_to_wb
from utils.paginations import MyPagination
from water_applets import settings

order_manager_router = Router(tags=["订单管理"], auth=ManagerAuthBearer())


@order_manager_router.get("/orders", summary="获取用户订单列表", response=List[OrderInfoResponseSchema])
@paginate(MyPagination)
@handle_exception("获取用户订单列表失败")
def get_orders(request, filters: ManagerOrderFiltersSchema = Query(...)):
    orders = OrderInfo.objects.all()
    orders = filters.filter(orders)
    return orders


@order_manager_router.post("/order/set_logistics_info/{order_id}", summary="设置订单发货信息")
@handle_exception("设置订单发货信息失败")
def set_logistics_info(request, order_id: int, data: OrderUpdateLogisticsSchema):
    order = OrderInfo.objects.get(id=order_id)
    order.logistics_id = data.logistics_id
    order.logistics_company = data.Logistics_company
    order.save()
    return R.ok("设置成功")


@order_manager_router.post("/order/refund/{order_id}", summary="订单退款")
@handle_exception("订单退款失败")
def order_refund(request, order_id: int, data: OrderRefundSchema):
    if not OrderInfo.objects.filter(id=order_id).exists():
        return R.fail("订单不存在")
    order = OrderInfo.objects.get(id=order_id)
    if data.refund_amount > order.actual_payment:
        return R.fail("退款金额大于实际支付金额")
    if data.after_sales_status == 4:
        order.after_sales_status = AfterSalesStatus.REFUND_REJECTED
        order.save()
        return R.ok("退款拒绝成功")
    with transaction.atomic():
        pay = WeChatPay(appid=settings.WECHAT_APPID,
                        api_key=settings.WECHAT_MERCHANT_KEY,
                        sub_appid=settings.WECHAT_APPID,
                        mch_id=settings.WECHAT_MERCHANT_ID)
        pay.refund.apply(total_fee=order.actual_payment * 100,
                         refund_fee=data.refund_money * 100,
                         out_refund_no=order.order_id,
                         transaction_id=order.transaction_id)
        order.after_sales_status = AfterSalesStatus.REFUNDED
        order.save()
    return R.ok("退款成功")


@order_manager_router.post("/vip_order/refund/{order_id}", summary="VIP订单退款")
@handle_exception("VIP订单退款失败")
def order_refund(request, order_id: int, data: OrderRefundSchema):
    if not VipOrderInfo.objects.filter(id=order_id).exists():
        return R.fail("订单不存在")
    order = VipOrderInfo.objects.get(id=order_id)
    if data.refund_amount > order.pay_money:
        return R.fail("退款金额大于实际支付金额")
    if data.after_sales_status == 4:
        order.after_sales_status = AfterSalesStatus.REFUND_REJECTED
        order.save()
        return R.ok("退款拒绝成功")
    with transaction.atomic():
        pay = WeChatPay(appid=settings.WECHAT_APPID,
                        api_key=settings.WECHAT_MERCHANT_KEY,
                        sub_appid=settings.WECHAT_APPID,
                        mch_id=settings.WECHAT_MERCHANT_ID)
        pay.refund.apply(total_fee=order.actual_payment * 100,
                         refund_fee=data.refund_money * 100,
                         out_refund_no=order.order_id,
                         transaction_id=order.transaction_id)
        order.after_sales_status = AfterSalesStatus.REFUNDED
        order.save()
    return R.ok("退款成功")


@order_manager_router.get("/vip/orders", summary="获取VIP订单列表", response=List[VipOrderInfoResponseSchema])
@handle_exception("获取VIP订单列表失败")
@paginate(MyPagination)
def get_vip_orders(request, filters: ManagerVipOrderFiltersSchema = Query(...)):
    orders = VipOrderInfo.objects.all()
    orders = filters.filter(orders)
    return orders


@order_manager_router.get("/agent/orders", summary="获取代理订单列表", response=List[AgentOrderInfoResponseSchema])
@handle_exception("获取代理订单列表失败")
@paginate(MyPagination)
def get_agent_orders(request, filters: ManagerAgentOrderFiltersSchema = Query(...)):
    orders = AgentOrderInfo.objects.all()
    orders = filters.filter(orders)
    return orders


@order_manager_router.get("/order/{order_id}", summary="获取用户订单详情")
@handle_exception("获取用户订单详情失败")
def get_order(request, order_id):
    order = OrderInfo.objects.aget(id=order_id)
    return R.ok(OrderInfoSerializer(order).data)


@order_manager_router.get("/vip/order/{order_id}", summary="获取vip订单详情")
@handle_exception("获取vip订单详情失败")
def get_vip_order(request, order_id: int):
    order = VipOrderInfo.objects.get(id=order_id)
    return R.ok(VipOrderInfoSerializer(order).data)


@order_manager_router.get("/agent/order/{order_id}", summary="获取代理订单详情")
@handle_exception("获取代理订单详情失败")
def get_agent_order(request, order_id: int):
    order = AgentOrderInfo.objects.get(id=order_id)
    return R.ok(AgentOrderInfoSerializer(order).data)


@order_manager_router.get("/orders/export", summary="导出用户订单列表")
@handle_exception("导出用户订单列表失败")
def export_orders(request, filters: ManagerOrderFiltersSchema = Query(...)):
    orders = OrderInfo.objects.all()
    orders = filters.filter(orders)
    aliases = [item.verbose_name for item in OrderInfo._meta.fields]
    field_names = [item.attname for item in OrderInfo._meta.fields]
    response = HttpResponse(content_type='application/vnd.ms-excel')
    response['Content-Disposition'] = 'attachment;filename=history.xls'
    wb = write_data_to_wb(aliases, field_names, orders)
    wb.save(response)
    return response


